import itertools

# 电阻备选值
resistor_values = [100, 220, 470, 1000, 2000, 4700, 5100, 6800, 10000, 12000, 15000, 20000, 22000, 47000, 51000, 100000]

# 计算输出电压Vout
def calculate_vout(vfb, r1, r2):
    return vfb * (1 + r1 / r2)

# 计算误差百分比
def calculate_error(expected_vout, actual_vout):
    return ((actual_vout - expected_vout) / expected_vout) * 100

# 串联电阻可能性（最多2个电阻串联）
def possible_resistors(values):
    return [(r,) for r in values] + [(r1, r2) for r1, r2 in itertools.combinations(values, 2)]

# 将电阻值格式化为字符串
def format_resistor_value(value):
    if value >= 1000:
        return f"{value / 1000:.1f}kΩ"
    return f"{value}Ω"

# 计算电阻组合
def find_best_resistors(vfb, vout, tolerance=1.0, max_results=3, force_single_resistor=False):
    best_combinations = []
    
    # 获取所有可能的电阻组合
    r1_combinations = possible_resistors(resistor_values)
    r2_combinations = possible_resistors(resistor_values)

    for r1_combo in r1_combinations:
        for r2_combo in r2_combinations:
            # 计算组合电阻值
            r1_value = sum(r1_combo)
            r2_value = sum(r2_combo)
            
            # 如果开启了强制单电阻组合模式，只考虑单个电阻的组合
            if force_single_resistor and len(r1_combo) > 1:
                continue
            if force_single_resistor and len(r2_combo) > 1:
                continue
            
            # 计算实际输出电压
            actual_vout = calculate_vout(vfb, r1_value, r2_value)
            
            # 计算误差
            error = calculate_error(vout, actual_vout)
            
            # 如果开启了强制单电阻组合模式，忽略误差检查
            if force_single_resistor or abs(error) <= tolerance:
                best_combinations.append({
                    'R1': r1_combo,
                    'R2': r2_combo,
                    'Actual_Vout': actual_vout,
                    'Error_Percentage': error
                })
    
    # 按误差绝对值排序，并返回最多max_results个组合
    best_combinations = sorted(best_combinations, key=lambda x: abs(x['Error_Percentage']))[:max_results]
    
    return best_combinations

# 输入验证函数
def get_float_input(prompt, default=None):
    while True:
        try:
            user_input = input(prompt).strip()
            if user_input == "" and default is not None:
                return default
            return float(user_input)
        except ValueError:
            print("无效输入，请输入一个有效的数字。")

def get_int_input(prompt, default=None):
    while True:
        try:
            user_input = input(prompt).strip()
            if user_input == "" and default is not None:
                return default
            return int(user_input)
        except ValueError:
            print("无效输入，请输入一个有效的整数。")

def get_yes_no_input(prompt, default="n"):
    while True:
        user_input = input(prompt).strip().lower()
        if user_input in ['y', 'n']:
            return user_input == 'y'
        elif user_input == "" and default in ['y', 'n']:
            return default == 'y'
        else:
            print("无效输入，请输入 Y 或 N。")

# 命令行交互
def main():
    print("DCDC反馈电压分压电阻计算器")
    
    # 显示电阻备选值并询问是否添加
    print("当前电阻备选值：")
    print(", ".join([f"{r}Ω" if r < 1000 else f"{r / 1000:.1f}kΩ" for r in resistor_values]))
    add_resistor = get_yes_no_input("是否需要添加新的电阻值? (Y/N): ")
    
    if add_resistor:
        while True:
            new_resistors = input("请输入要添加的电阻值（单位：Ω，用空格分隔多个电阻值）：").strip().split()
            try:
                new_resistors = [int(value) for value in new_resistors]
                # 去重并添加新的电阻
                new_resistors = list(set(new_resistors))  # 去重
                resistor_values.extend(new_resistors)
                
                # 打印当前电阻备选值并高亮新添加的电阻
                print("已更新的电阻备选值：")
                updated_resistor_values = [f"{r}Ω" if r < 1000 else f"{r / 1000:.1f}kΩ" for r in resistor_values]
                updated_resistor_str = ", ".join(updated_resistor_values)
                
                # 高亮新添加的电阻
                new_resistor_str = ", ".join([f"{r}Ω" if r < 1000 else f"{r / 1000:.1f}kΩ" for r in new_resistors])
                updated_resistor_str = updated_resistor_str.replace(new_resistor_str, f"\033[1;32m{new_resistor_str}\033[0m")  # 高亮显示
                
                print(updated_resistor_str)
                break
            except ValueError:
                print("输入无效，请确保您输入的是数字。")
    
    # 获取用户输入的反馈电压和期望输出电压
    vfb = get_float_input("请输入反馈电压 Vfb: ")
    vout = get_float_input("请输入期望输出电压 Vout: ")
    
    # 获取用户是否开启强制单电阻组合的选项
    force_single_resistor = get_yes_no_input("是否开启强制单电阻组合 (Y/N): ")
    
    # 如果开启强制单电阻组合，不再询问误差容差
    if not force_single_resistor:
        tolerance = get_float_input("请输入误差容差百分比 (默认1%): ", default=1.0)
    else:
        tolerance = 1.0  # 默认容差为1%，但实际不被使用
    
    max_results = get_int_input("请输入返回的最佳结果数量 (默认3组): ", default=3)

    # 计算最佳电阻值
    best_combinations = find_best_resistors(vfb, vout, tolerance, max_results, force_single_resistor)

    if not best_combinations:
        print("没有找到符合要求的电阻组合，请尝试增加容差范围。")
    else:
        print(f"{'组合':<5} {'R1':<30} {'R2':<30} {'输出电压 Vout':<20} {'误差':<10}")
        print("=" * 100)
        for i, combo in enumerate(best_combinations):
            r1 = " + ".join([format_resistor_value(r) for r in combo['R1']])
            r2 = " + ".join([format_resistor_value(r) for r in combo['R2']])
            actual_vout = combo['Actual_Vout']
            error = combo['Error_Percentage']
            print(f"{i+1:<5} {r1:<30} {r2:<30} {actual_vout:<20.4f} {error:<10.2f}%")

    input("按Enter键退出..")

if __name__ == "__main__":
    main()
